package com.yaodian100.ec.shelf.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.admin.entity.User;
import com.yaodian100.core.admin.entity.UserPermission;
import com.yaodian100.core.admin.entity.Permission.Type;
import com.yaodian100.core.admin.service.UserService;
import com.yaodian100.core.admin.utils.AdminHelper;
import com.yaodian100.core.common.dao.ObjectDao;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.dao.impl.CriteriaInRlike;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.common.utils.DateUtil;
import com.yaodian100.core.logger.service.LogService;
import com.yaodian100.ec.category.service.CategoryService;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.service.ProductService;
import com.yaodian100.ec.shelf.entity.Shelf;
import com.yaodian100.ec.shelf.entity.ViewFlagProduct;
import com.yaodian100.ec.shelf.entity.ViewShelf;
import com.yaodian100.ec.shelf.entity.ViewShelfProduct;
import com.yaodian100.ec.shelf.service.ShelfService;

public class ShelfServiceImpl extends DomainServiceImpl<Shelf> implements ShelfService {
	private ObjectDao<ViewShelfProduct> viewShelfProductDao;
	private ObjectDao<ViewFlagProduct> viewFlagProductDao;
	private final static String[] SORT_BY = new String[] { "startDate desc", "modifyDate desc" };

	@Resource
	private LogService logService;
	private String finalStatus = "SHF500";
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private UserService userService;
	private final String STRING_SYMBOL = "/";
	@Resource
	private ProductService productService;
	@Resource
	private CategoryService categoryService;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.shelf.service.ShelfService#getPublishShelfs(java.lang.String, java.lang.String[], int, int)
	 */
	@Override
	public List<ViewShelf> getPublishShelfs(Long categoryId, String[] productIds) throws CoreException {
		StringBuffer sb = new StringBuffer();
		List attrs = new ArrayList();
		if (null != categoryId) {
			sb.append("select s from ViewShelf s, ProductCategory pc where pc.productId = s.productId ");
			sb.append("and pc.categoryId = ? ");
			attrs.add(categoryId);
			sb.append("and s.shelfStatus= ? ");
			attrs.add(finalStatus);
		} else {
			sb.append("select s from ViewShelf s ");
			sb.append("where s.shelfStatus = ? ");
			attrs.add(finalStatus);
		}
		if (productIds != null) {
			sb.append(" and s.productId in (");
			for (int i = 0; i < productIds.length; i++) {
				if (i == 0) {
					sb.append("?");
				} else {
					sb.append(", ?");
				}
				attrs.add(productIds[i]);
			}
			sb.append(")");
		}
		return getDao().getQueryByList(sb.toString(), attrs, 0, -1);
	}

	@Override
	public Shelf getShelfByProductId(String productId, Date startDate, Date endDate) throws CoreException {
		CommonCriteria crit = new CommonCriteria();
		crit.addEq("productId", productId);
		crit.addLe("startDate", startDate);
		crit.addGe("endDate", endDate);
		crit.addEq("shelfStatus", finalStatus);
		List<Shelf> l = this.getDao().getListPageable(crit, SORT_BY, 0, 1);
		if (null != l && !l.isEmpty() && l.size() > 0) {
			return l.get(0);
		} else {
			return null;
		}
	}

	/*
	 * 最新上檔中的上架區間
	 * 
	 * @see com.yaodian100.ec.shelf.service.ShelfService#getActiveShelfByProductId(java.lang.String)
	 */
	public Shelf getActiveShelfByProductId(String productId) throws CoreException {
		Date now = DateUtil.getCurrentTime();
		Shelf shelf = getShelfByProductId(productId, now, now);
		return shelf;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.shelf.service.ShelfService#getViewFlagProduct(com.yaodian100.core.common.dao.impl.CommonCriteria
	 * , java.lang.String[], int, int)
	 */
	@Override
	public List<ViewFlagProduct> getViewFlagProduct(CommonCriteria criteria, String[] sortBy, int startNode, int pageSize)
			throws CoreException {
		return viewFlagProductDao.getListPageable(criteria, sortBy, startNode, pageSize);
	}

	public List<ViewFlagProduct> getViewFlagProductForIdxTab3(String date, String orderBy, int startNode, int pageSize)
			throws CoreException {
		StringBuffer sb = new StringBuffer();
		sb.append("from ViewFlagProduct where categoryPath not like '8/%' ");
		sb.append("order by ").append(orderBy).append(" ,shelfModifyDate ");
		return viewFlagProductDao.getQueryByList(sb.toString(), null, startNode, pageSize);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.shelf.service.ShelfService#getViewFlagProductSize(com.yaodian100.core.common.dao.impl.CommonCriteria
	 * )
	 */
	@Override
	public Number getViewFlagProductSize(CommonCriteria criteria) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");// 分線維護權限檢核
		return viewFlagProductDao.getListSize(critInRlike);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.shelf.service.ShelfService#getPublishShelfs(java.lang.Long, int, int, java.lang.String[])
	 */
	@Override
	public List<ViewShelfProduct> getViewShelfProduct(CommonCriteria criteria, String[] sortBy, int startNode,
			int pageSize) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");// 分線維護權限檢核
		return getViewShelfProductDao().getListPageable(critInRlike, sortBy, startNode, pageSize);
	}

	public ObjectDao<ViewShelfProduct> getViewShelfProductDao() {
		return viewShelfProductDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.shelf.service.ShelfService#getViewShelfProductSize(java.lang.Long)
	 */
	@Override
	public Number getViewShelfProductSize(CommonCriteria criteria) throws CoreException {
		CriteriaInRlike critInRlike = mergeCritInRlike(criteria, "categoryPath");// 分線維護權限檢核
		return viewShelfProductDao.getListSize(critInRlike);
	}

	@Transactional(readOnly = false, timeout = 5)
	public Shelf saveOrUpdateShelf(Shelf shelf) throws CoreException {
		try {
			getDao().saveOrUpdate(shelf);
			logService.save(getClass().getSimpleName(), "saveOrUpdateShelf", shelf);
		} catch (CoreException e) {
			throw new CoreException("新增/修改上架檔失败");
		}
		return shelf;
	}

	@Transactional(readOnly = false, timeout = 5)
	public Shelf addShelf(Shelf shelf) throws CoreException {
		try {
			Product p = productService.get(shelf.getProductId());
			if (p != null) {
				// 预设是通过审核(以设好ShelfStatus,ApproveDate,ApproveUser)，除非遇负毛利
				BigDecimal grossProfit = categoryService.getGrossProfitByPath(p.getMainCategoryPath());
				// 小于毛利率时需审核
				if (null == grossProfit
						|| (shelf.getShelfPrice().subtract(p.getProductCost()).multiply(new BigDecimal("100")).divide(shelf
								.getShelfPrice(), 1)).floatValue() < grossProfit.floatValue()) {
					shelf.setShelfStatus("SHF000");
					shelf.setApproveDate(null);
					shelf.setApproveUser(null);
				}
				saveOrUpdateShelf(shelf);
			} else {
				throw new CoreException("新增/修改上架檔失败:商品错误");
			}
		} catch (CoreException e) {
			throw new CoreException("新增/修改上架檔失败");
		}
		return shelf;
	}

	/**
	 * @param finalStatus the finalStatus to set
	 */
	public void setFinalStatus(String finalStatus) {
		this.finalStatus = finalStatus;
	}

	/**
	 * @param viewFlagProductDao the viewFlagProductDao to set
	 */
	public void setViewFlagProductDao(ObjectDao<ViewFlagProduct> viewFlagProductDao) {
		this.viewFlagProductDao = viewFlagProductDao;
	}

	public void setViewShelfProductDao(ObjectDao<ViewShelfProduct> viewShelfProductDao) {
		this.viewShelfProductDao = viewShelfProductDao;
	}

	@Override
	@Transactional(readOnly = false)
	public Shelf update(Shelf shelf) throws CoreException {
		try {
			getDao().saveOrUpdate(shelf);
			logService.save(getClass().getSimpleName(), "saveOrUpdateShelf", shelf);
		} catch (CoreException e) {
			throw new CoreException("新增/修改上架檔失败");
		}
		return shelf;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.shelf.service.ShelfService#getShelfHistory(java.lang.String)
	 */
	@Override
	public List<Map<String, Object>> getShelfHistory(String productId) throws Exception {
		List<Map<String, Object>> shelfHistoryList = jdbcTemplate
				.queryForList(
						"select * from EC_SHELF_MAIN_HISTORY where product_id = ? and shelf_status in ('SHF000','SHF500') and (sysdate between start_date and end_date or start_date >= sysdate or end_date >= sysdate)",
						new Object[] { productId });
		return shelfHistoryList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.shelf.service.ShelfService#getShelfApproveList(com.yaodian100.core.common.dao.impl.CommonCriteria
	 * , java.lang.String[], int, int)
	 */
	@Override
	public List<Shelf> getShelfApproveList(Map<String, Object> attrs, String[] sortBy, int startNode, int pageSize)
			throws CoreException {
		StringBuilder sb = new StringBuilder();
		sb.append("select s from Shelf s , Product p where s.productId = p.productId ");
		sb.append("and p.productType != '6' ");
		if (attrs.size() > 0) {
			if (null != attrs.get("createDate")) {
				sb.append("and s.createDate >= :createDate ");
			}
			if (null != attrs.get("createUser")) {
				sb.append("and s.createUser = :createUser ");
			}
			if (null != attrs.get("shelfStatus")) {
				sb.append("and s.shelfStatus = :shelfStatus ");
			}
			if (null != attrs.get("productId")) {
				sb.append("and s.productId = :productId ");
			}
		}
		sb.append(mergeHqlInRlike("p.category.categoryPath"));// 分線維護權限檢核
		List<Shelf> shelfs = getDao().getQueryByMap(sb.toString(), attrs, startNode, pageSize);
		sb.setLength(0);
		return shelfs;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.shelf.service.ShelfService#getShelfApproveListSize(java.util.Map)
	 */
	@Override
	public Number getShelfApproveListSize(Map<String, Object> attrs) throws CoreException {
		StringBuilder sb = new StringBuilder();
		sb.append("select count(s) from Shelf s , Product p where s.productId = p.productId ");
		sb.append("and p.productType != '6' ");
		if (attrs.size() > 0) {
			if (null != attrs.get("createDate")) {
				sb.append("and s.createDate >= :createDate ");
			}
			if (null != attrs.get("createUser")) {
				sb.append("and s.createUser = :createUser ");
			}
			if (null != attrs.get("shelfStatus")) {
				sb.append("and s.shelfStatus = :shelfStatus ");
			}
			if (null != attrs.get("productId")) {
				sb.append("and s.productId = :productId ");
			}
		}
		sb.append(mergeHqlInRlike("p.category.categoryPath"));// 分線維護權限檢核
		List<Object> objs = getDao().getQueryByMap(sb.toString(), attrs, 0, -1);
		sb.setLength(0);
		if (objs.size() > 0) {
			return NumberUtils.createNumber(objs.get(0).toString());
		} else {
			return 0;
		}
	}

	/**
	 * 分線維護權限檢核
	 * 
	 * @param commcriteria
	 * @return
	 */
	CriteriaInRlike mergeCritInRlike(CommonCriteria criteria, String tableParam) {
		CriteriaInRlike critInRlike = null;
		User user = AdminHelper.getUser();
		if (null != user) {
			if (null == criteria) {
				criteria = new CommonCriteria();
			}
			critInRlike = new CriteriaInRlike(criteria);
			// 若 user 是 PM部門, 檢核 product.category 的 orgnizationPath 是否合乎規定
			List<Serializable> prs = new ArrayList<Serializable>();
			for (UserPermission up : user.getPermissions(Type.CATEGORY).values()) {
				prs.add(up.getPermissionCode() + STRING_SYMBOL);
			}
			critInRlike.addInRlike(tableParam, prs);
		} else {
			if (null == criteria) {
				criteria = new CommonCriteria();
			}
			critInRlike = new CriteriaInRlike(criteria);
		}
		return critInRlike;
	}

	/**
	 * 分線維護權限檢核
	 * 
	 * @param parentId
	 * @return
	 */
	String mergeHqlInRlike(String tableParam) {
		String premissString = "";
		User user = AdminHelper.getUser();
		if (null != user) {
			StringBuffer sb = new StringBuffer();
			// 若 user 是 PM部門, 檢核 product.category 的 orgnizationPath 是否合乎規定
			if (user.getPermissions(Type.CATEGORY).size() > 0) {
				sb.append("and ( ");
				int i = 0;
				for (UserPermission up : user.getPermissions(Type.CATEGORY).values()) {
					sb.append(tableParam).append(" like '").append(up.getPermissionCode()).append(STRING_SYMBOL).append("%'");
					if (i != user.getPermissions(Type.CATEGORY).size() - 1) {
						sb.append(" or ");
					}
					i++;
				}
				sb.append(" ) ");
				premissString = sb.toString();
			}
		}
		return premissString;
	}
}